package com.sanq.product.books.controller;

import com.sanq.product.books.config.Common;
import com.sanq.product.books.config.EsIndexs;
import com.sanq.product.books.config.Redis;
import com.sanq.product.books.entity.module.ServiceModule;
import com.sanq.product.books.entity.vo.BaseReportVo;
import com.sanq.product.books.es.service.VisiLogSearchService;
import com.sanq.product.books.service.BaseReportService;
import com.sanq.product.books.service.OrdersService;
import com.sanq.product.books.service.UsersService;
import com.sanq.product.books.utils.WebUtil;
import com.sanq.product.config.utils.annotation.LogAnnotation;
import com.sanq.product.config.utils.date.DateUtil;
import com.sanq.product.config.utils.date.LocalDateUtils;
import com.sanq.product.config.utils.entity.Response;
import com.sanq.product.config.utils.futures.Future;
import com.sanq.product.config.utils.string.StringUtil;
import com.sanq.product.config.utils.web.LogUtil;
import com.sanq.product.redis.service.JedisPoolService;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;

/**
 * com.sanq.product.books.controller.SummaryController
 *
 * @author sanq.Yan
 * @date 2019/8/25
 */
@RestController
@RequestMapping("/api/summary")
public class SummaryController {

    @Resource
    private UsersService usersService;
    @Resource
    private ThreadPoolTaskExecutor taskExecutor;
    @Resource
    private JedisPoolService jedisPoolService;
    @Resource
    private OrdersService ordersService;
    @Resource
    private BaseReportService baseReportService;
    @Resource
    private VisiLogSearchService visiLogSearchService;

    @LogAnnotation(description = "得到用户汇总")
    @GetMapping(value = "/user")
    public Response user(HttpServletRequest request) {

        //新增用户	活跃用户	累计用户
        ServiceModule module = WebUtil.getModule(0);

        Map<String, Integer> map = usersService.findSummaryUser(module);

        map.put("active", StringUtil.toInteger(jedisPoolService.bitCount(Redis.ReplaceKey.getActiveUsers(LocalDateUtils.nowTime()))));

        return new Response().success(map);
    }

    @LogAnnotation(description = "得到订单汇总")
    @GetMapping(value = "/order")
    public Response order(HttpServletRequest request) {

//        订单	充值金额	总金额
        ServiceModule module = WebUtil.getModule(0);

        Map<String, Integer> map = ordersService.findSummaryOrder(module);

        return new Response().success(map);
    }

    @LogAnnotation(description = "折线图汇总")
    @GetMapping(value = "/lines")
    public Response lines(HttpServletRequest request) {


        Map<String, Object> map = new Future.Builder()
                .setExecutor(taskExecutor)
                .option("newUserLine", () -> {

                    List<Map<String, Object>> userMapList = usersService.findLineDataGroupTime();

                    return getResultMap(userMapList);
                })
                .option("activeUserLine", () -> getActiveLines('A'))
                .option("newOrderLine", () -> {
                    List<Map<String, Object>> orderMapList = ordersService.findLineDataGroupTime();

                    return getResultMap(orderMapList);
                })
                .option("newMoneyLine", () -> {
                    List<Map<String, Object>> orderMoneyMapList = ordersService.findTotalMoneyLineGroupTime();

                    if (orderMoneyMapList != null && !orderMoneyMapList.isEmpty()) {
                        List<BigDecimal> counts = new ArrayList<>(orderMoneyMapList.size());
                        List<String> times = new ArrayList<>(orderMoneyMapList.size());

                        WeakHashMap<String, List> resultMap = new WeakHashMap<>(2);

                        orderMoneyMapList.stream().forEach(item -> {
                            counts.add((BigDecimal) item.get("_sumMoney"));
                            times.add((String) item.get("time"));
                        });

                        resultMap.put("money", counts);
                        resultMap.put("times", times);

                        return resultMap;
                    }

                    return null;
                })
                .build()
                .run();


        return new Response().success(map);
    }

    private Object getResultMap(List<Map<String, Object>> list) {
        if (list != null && !list.isEmpty()) {
            List<Integer> counts = new ArrayList<>(list.size());
            List<String> times = new ArrayList<>(list.size());

            WeakHashMap<String, List> resultMap = new WeakHashMap<>(2);

            list.stream().forEach(item -> {
                counts.add(StringUtil.toInteger(item.get("_count")));
                times.add(item.get("time").toString());
            });
            resultMap.put("counts", counts);
            resultMap.put("times", times);

            return resultMap;
        }
        return null;
    }

    private Object getActiveLines(char a) {
        List<Map<String, Object>> activeUserList = baseReportService.findLineDataGroupTime(a);

        final Date now = LocalDateUtils.nowTime();
        String indexName = null;
        switch (a) {
            case 'A':
                activeUserList.add(0, new HashMap<String, Object>() {{
                    put("_count", StringUtil.toInteger(jedisPoolService.bitCount(Redis.ReplaceKey.getActiveUsers(now))));
                    put("time", Common.DateConvert.getDate(now));
                }});
                break;
            case 'P':
                indexName = EsIndexs.ReplaceIndex.getVisiLogIndex(now);
                BaseReportVo pvReport = visiLogSearchService.getBaseReport(indexName);

                activeUserList.add(0, new HashMap<String, Object>() {{
                    put("_count", pvReport != null ? pvReport.getViews() : 0);
                    put("time", Common.DateConvert.getDate(now));
                }});

                break;
            case 'I':
                indexName = EsIndexs.ReplaceIndex.getVisiLogIndex(now);
                BaseReportVo uvReport = visiLogSearchService.getBaseReport(indexName);

                activeUserList.add(0, new HashMap<String, Object>() {{
                    put("_count", uvReport != null ? uvReport.getIpViews() : 0);
                    put("time", Common.DateConvert.getDate(now));
                }});
                break;
        }

        return getResultMap(activeUserList);
    }

    @LogAnnotation(description = "访问统计折线图汇总")
    @GetMapping(value = "/report_line")
    public Response reportLine(HttpServletRequest request) {

        Map<String, Object> map = new Future.Builder()
                .setExecutor(taskExecutor)
                .option("pvLine", () -> getActiveLines('P'))
                .option("uvLine", () -> getActiveLines('I'))
                // 设备柱状图 pv
                // 设备柱状图 ip
                .build()
                .run();

        return new Response().success(map);
    }
}
